閱讀有關元件的 lifecycle hook - ngDoCheck 的內容
呼叫時機: 在每一次 ngOnChanges 呼叫結束後就會被呼叫。在首次的 ngOnInit 完成後,就會立即被呼叫。
在昨天的文章中,我們有介紹到了 ngOnChanges
的特性,當某個 @Input
屬性去參照了某個物件,但該物件只有改變其內部屬性成員的值,並沒有指向一個更新後的物件位址的話,是不會觸發 ngOnChanges
的 lifecycle hook 的。
那萬一,我們真的很想要在該物件內容被更改的時候,通知我們它被更動的話要怎麼辦呢?
這個時候,就可以使用 ngDoCheck
這個 lifecycle hook 來達成以上的效果囉~
這邊來寫個小範例
[childComponent - View]
<div>
<p>
<label for="name">Hero Name</label>
<input type="text" id="name" [(ngModel)]="hero.name" />
</p>
<p>
<label for="power">Hero Power</label>
<input type="text" id="power" [(ngModel)]="hero.power" />
</p>
</div>
[childComponent - TypeScript]
export class HeroComponent implements OnInit, OnChanges, DoCheck {
@Input() hero;
constructor() {}
ngOnInit() {}
ngDoCheck() {
console.log('ngDoCheck');
}
ngOnChanges() {
console.log('ngOnChanges');
}
}
[parentComponent - View]
<app-hero [hero]="hero"></app-hero>
[parentComponent - TypeScript]
export class AppComponent {
hero = {
name: 'wu-kung',
power: 'HaMeHaMeHa',
};
}
以上的範例,可以看到在子元件的部分,定義了一個 @Input 屬性 hero 取得父元件的 hero 資料。
並且在子元件定義了 ngDoCheck 和 ngOnChanges 來看看,當改變 hero 的屬性內容的時候,是哪一個 lifecycle hook 會被驅動。
操作如下
可以看到,當改變 input 欄位的內容時,只有 ngDoCheck 會觸發,就算是只有點擊 input 欄位,也會觸發到 ngDoCheck
。反觀 ngOnChanges
是一次都沒有被觸發到。
當你有一些內容真的想要監測的話,又無法被 ngOnChanges 監測到的時候,就可以使用 ngDoCheck 了。
但是,如同上面範例操作的那樣,ngDoCheck 是非常容易就被觸發了,如果你在 ngDoCheck 裡面放入太大量或複雜的運算的話,是很有可能會嚴重影響你的產品的運行速度,進而讓使用者有不好的體驗的。
所以,在 ngDoCheck 的內容應該要放一些比較輕量的內容才對。
來做個總結
ngDoCheck
來達到這種效果,來突破 ngOnChanges
的限制。